home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -serious- / programming / other / mesa / mesa-glut / src-glut.aos / glutstring.c < prev    next >
C/C++ Source or Header  |  2000-02-23  |  18KB  |  737 lines

  1. /*
  2.  * Amiga GLUT graphics library toolkit
  3.  * Version:  1.1
  4.  * Copyright (C) 1998 Jarno van der Linden
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU Library General Public
  8.  * License as published by the Free Software Foundation; either
  9.  * version 2 of the License, or (at your option) any later version.
  10.  *
  11.  * This library is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * Library General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU Library General Public
  17.  * License along with this library; if not, write to the Free
  18.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. /*
  22.  * glutString.c
  23.  *
  24.  * Version 1.0  27 Jun 1998
  25.  * by Jarno van der Linden
  26.  * jarno@kcbbs.gen.nz
  27.  *
  28.  */
  29.  
  30. #include "glutstuff.h"
  31.  
  32. static char *compstr[] =
  33. {
  34.   "none", "=", "!=", "<=", ">=", ">", "<", "~"
  35. };
  36. static char *capstr[] =
  37. {
  38.   "rgba", "bufsize", "double", "stereo", "auxbufs", "red", "green", "blue", "alpha",
  39.   "depth", "stencil", "acred", "acgreen", "acblue", "acalpha", "level", "xvisual",
  40.   "transparent", "samples", "xstaticgray", "xgrayscale", "xstaticcolor", "xpseudocolor",
  41.   "xtruecolor", "xdirectcolor", "slow", "conformant", "num"
  42. };
  43.  
  44. /* Frame buffer capability macros and types. */
  45. #define RGBA                    0
  46. #define BUFFER_SIZE             1
  47. #define DOUBLEBUFFER            2
  48. #define STEREO                  3
  49. #define AUX_BUFFERS             4
  50. #define RED_SIZE                5                /* Used as mask bit for
  51.                                  * "color selected". */
  52. #define GREEN_SIZE              6
  53. #define BLUE_SIZE               7
  54. #define ALPHA_SIZE              8
  55. #define DEPTH_SIZE              9
  56. #define STENCIL_SIZE            10
  57. #define ACCUM_RED_SIZE          11                /* Used as mask bit for
  58.                                  * "acc selected". */
  59. #define ACCUM_GREEN_SIZE        12
  60. #define ACCUM_BLUE_SIZE         13
  61. #define ACCUM_ALPHA_SIZE        14
  62. #define LEVEL                   15
  63.  
  64. #define NUM_GLXCAPS             (LEVEL + 1)
  65.  
  66. #define XVISUAL                 (NUM_GLXCAPS + 0)
  67. #define TRANSPARENT             (NUM_GLXCAPS + 1)
  68. #define SAMPLES                 (NUM_GLXCAPS + 2)
  69. #define XSTATICGRAY             (NUM_GLXCAPS + 3)        /* Used as mask bit for
  70.                                  * "any visual type selected". */
  71. #define XGRAYSCALE              (NUM_GLXCAPS + 4)
  72. #define XSTATICCOLOR            (NUM_GLXCAPS + 5)
  73. #define XPSEUDOCOLOR            (NUM_GLXCAPS + 6)
  74. #define XTRUECOLOR              (NUM_GLXCAPS + 7)
  75. #define XDIRECTCOLOR            (NUM_GLXCAPS + 8)
  76. #define SLOW                    (NUM_GLXCAPS + 9)
  77. #define CONFORMANT              (NUM_GLXCAPS + 10)
  78.  
  79. #define NUM_CAPS                (NUM_GLXCAPS + 11)
  80.  
  81. /* Frame buffer capablities that don't have a corresponding
  82.  * FrameBufferMode entry.  These get used as mask bits.
  83.  */
  84. #define NUM                     (NUM_CAPS + 0)
  85. #define RGBA_MODE               (NUM_CAPS + 1)
  86. #define CI_MODE                 (NUM_CAPS + 2)
  87. #define LUMINANCE_MODE        (NUM_CAPS + 3)
  88.  
  89. #define NONE            0
  90. #define EQ            1
  91. #define NEQ            2
  92. #define LTE            3
  93. #define GTE            4
  94. #define GT            5
  95. #define LT            6
  96. #define MIN            7
  97.  
  98. typedef struct _Criterion {
  99.   int capability;
  100.   int comparison;
  101.   int value;
  102. } Criterion;
  103.  
  104. /* converts string-part to criterion */
  105. int parseString(char *word, int *mode)
  106. {
  107.   char *cstr, *vstr, *response;
  108.   int comparator, value;
  109.   int rgb, rgba, acc, acca, count, i;
  110.  
  111.   cstr = strpbrk(word, "=><!~");
  112.   if (cstr) {
  113.     switch (cstr[0]) {
  114.       case '=':
  115.     comparator = EQ;
  116.     vstr = &cstr[1];
  117.     break;
  118.       case '~':
  119.     comparator = MIN;
  120.     vstr = &cstr[1];
  121.     break;
  122.       case '>':
  123.     if (cstr[1] == '=') {
  124.       comparator = GTE;
  125.       vstr = &cstr[2];
  126.     }
  127.     else {
  128.       comparator = GT;
  129.       vstr = &cstr[1];
  130.     }
  131.     break;
  132.       case '<':
  133.     if (cstr[1] == '=') {
  134.       comparator = LTE;
  135.       vstr = &cstr[2];
  136.     }
  137.     else {
  138.       comparator = LT;
  139.       vstr = &cstr[1];
  140.     }
  141.     break;
  142.       case '!':
  143.     if (cstr[1] == '=') {
  144.       comparator = NEQ;
  145.       vstr = &cstr[2];
  146.     }
  147.     else {
  148.       return -1;
  149.     }
  150.     break;
  151.       default:
  152.     return -1;
  153.     }
  154.     value = (int)strtol(vstr, &response, 0);
  155.     if (response == vstr) {
  156.       /* Not a valid number. */
  157.       return -1;
  158.     }
  159.     *cstr = '\0';
  160.   }
  161.   else {
  162.     comparator = NONE;
  163.   }
  164.   switch (word[0]) {
  165.     case 'a':
  166.       if (!strcmp(word, "alpha")) {
  167.     criterion[0].capability = ALPHA_SIZE;
  168.     if (comparator == NONE) {
  169.       criterion[0].comparison = GTE;
  170.       criterion[0].value = 1;
  171.     }
  172.     else {
  173.       criterion[0].comparison = comparator;
  174.       criterion[0].value = value;
  175.     }
  176.     *mode |= (1 << RGBA);
  177.     *mode |= (1 << ALPHA_SIZE);
  178.     *mode |= (1 << RGBA_MODE);
  179.     return 1;
  180.       }
  181.       acca = !strcmp(word, "acca");
  182.       acc = !strcmp(word, "acc");
  183.       if (acc || acca) {
  184.     criterion[0].capability = ACCUM_RED_SIZE;
  185.     criterion[1].capability = ACCUM_GREEN_SIZE;
  186.     criterion[2].capability = ACCUM_BLUE_SIZE;
  187.     criterion[3].capability = ACCUM_ALPHA_SIZE;
  188.     if (acca) {
  189.       count = 4;
  190.     }
  191.     else {
  192.       count = 3;
  193.       criterion[3].comparison = MIN;
  194.       criterion[3].value = 0;
  195.     }
  196.     if (comparator == NONE) {
  197.       comparator = GTE;
  198.       value = 8;
  199.     }
  200.     for (i = 0; i < count; i++) {
  201.       criterion[i].comparison = comparator;
  202.       criterion[i].value = value;
  203.     }
  204.     *mode |= (1 << ACCUM_RED_SIZE);
  205.     return 4;
  206.       }
  207.       if (!strcmp(word, "auxbufs")) {
  208.     criterion[0].capability = AUX_BUFFERS;
  209.     if (comparator == NONE) {
  210.       criterion[0].comparison = MIN;
  211.       criterion[0].value = 1;
  212.     }
  213.     else {
  214.       criterion[0].comparison = comparator;
  215.       criterion[0].value = value;
  216.     }
  217.     *mode |= (1 << AUX_BUFFERS);
  218.     return 1;
  219.       }
  220.       return -1;
  221.     case 'b':
  222.       if (!strcmp(word, "blue")) {
  223.     criterion[0].capability = BLUE_SIZE;
  224.     if (comparator == NONE) {
  225.       criterion[0].comparison = GTE;
  226.       criterion[0].value = 1;
  227.     }
  228.     else {
  229.       criterion[0].comparison = comparator;
  230.       criterion[0].value = value;
  231.     }
  232.     *mode |= (1 << RGBA);
  233.     *mode |= (1 << RGBA_MODE);
  234.     return 1;
  235.       }
  236.       if (!strcmp(word, "buffer")) {
  237.     criterion[0].capability = BUFFER_SIZE;
  238.     if (comparator == NONE) {
  239.       criterion[0].comparison = GTE;
  240.       criterion[0].value = 1;
  241.     }
  242.     else {
  243.       criterion[0].comparison = comparator;
  244.       criterion[0].value = value;
  245.     }
  246.     return 1;
  247.       }
  248.       return -1;
  249.     case 'c':
  250.       if (!strcmp(word, "conformant")) {
  251.     criterion[0].capability = CONFORMANT;
  252.     if (comparator == NONE) {
  253.       criterion[0].comparison = EQ;
  254.       criterion[0].value = 1;
  255.     }
  256.     else {
  257.       criterion[0].comparison = comparator;
  258.       criterion[0].value = value;
  259.     }
  260.     *mode |= (1 << CONFORMANT);
  261.     return 1;
  262.       }
  263.       return -1;
  264.     case 'd':
  265.       if (!strcmp(word, "depth")) {
  266.     criterion[0].capability = DEPTH_SIZE;
  267.     if (comparator == NONE) {
  268.       criterion[0].comparison = GTE;
  269.       criterion[0].value = 12;
  270.     }
  271.     else {
  272.       criterion[0].comparison = comparator;
  273.       criterion[0].value = value;
  274.     }
  275.     *mode |= (1 << DEPTH_SIZE);
  276.     return 1;
  277.       }
  278.       if (!strcmp(word, "double")) {
  279.     criterion[0].capability = DOUBLEBUFFER;
  280.     if (comparator == NONE) {
  281.       criterion[0].comparison = EQ;
  282.       criterion[0].value = 1;
  283.     }
  284.     else {
  285.       criterion[0].comparison = comparator;
  286.       criterion[0].value = value;
  287.     }
  288.     *mode |= (1 << DOUBLEBUFFER);
  289.     return 1;
  290.       }
  291.       return -1;
  292.     case 'g':
  293.       if (!strcmp(word, "green")) {
  294.     criterion[0].capability = GREEN_SIZE;
  295.     if (comparator == NONE) {
  296.       criterion[0].comparison = GTE;
  297.       criterion[0].value = 1;
  298.     }
  299.     else {
  300.       criterion[0].comparison = comparator;
  301.       criterion[0].value = value;
  302.     }
  303.     *mode |= (1 << RGBA);
  304.     *mode |= (1 << RGBA_MODE);
  305.     return 1;
  306.       }
  307.       return -1;
  308.     case 'i':
  309.       if (!strcmp(word, "index")) {
  310.     criterion[0].capability = RGBA;
  311.     criterion[0].comparison = EQ;
  312.     criterion[0].value = 0;
  313.     criterion[1].capability = BUFFER_SIZE;
  314.     if (comparator == NONE) {
  315.       criterion[1].comparison = GTE;
  316.       criterion[1].value = 1;
  317.     }
  318.     else {
  319.       criterion[1].comparison = comparator;
  320.       criterion[1].value = value;
  321.     }
  322.     *mode |= (1 << RGBA);
  323.     *mode |= (1 << CI_MODE);
  324.     return 2;
  325.       }
  326.       return -1;
  327.     case 'l':
  328.       if (!strcmp(word, "luminance")) {
  329.     criterion[0].capability = RGBA;
  330.     criterion[0].comparison = EQ;
  331.     criterion[0].value = 1;
  332.  
  333.     criterion[1].capability = RED_SIZE;
  334.     if (comparator == NONE) {
  335.       criterion[1].comparison = GTE;
  336.       criterion[1].value = 1;
  337.     }
  338.     else {
  339.       criterion[1].comparison = comparator;
  340.       criterion[1].value = value;
  341.     }
  342.  
  343.     criterion[2].capability = GREEN_SIZE;
  344.     criterion[2].comparison = EQ;
  345.     criterion[2].value = 0;
  346.  
  347.     criterion[3].capability = BLUE_SIZE;
  348.     criterion[3].comparison = EQ;
  349.     criterion[3].value = 0;
  350.     *mode |= (1 << RGBA);
  351.     *mode |= (1 << RGBA_MODE);
  352.     *mode |= (1 << LUMINANCE_MODE);
  353.     return 4;
  354.       }
  355.       return -1;
  356.     case 'n':
  357.       if (!strcmp(word, "num")) {
  358.     criterion[0].capability = NUM;
  359.     if (comparator == NONE) {
  360.       return -1;
  361.     }
  362.     else {
  363.       criterion[0].comparison = comparator;
  364.       criterion[0].value = value;
  365.       return 1;
  366.     }
  367.       }
  368.       return -1;
  369.     case 'r':
  370.       if (!strcmp(word, "red")) {
  371.     criterion[0].capability = RED_SIZE;
  372.     if (comparator == NONE) {
  373.       criterion[0].comparison = GTE;
  374.       criterion[0].value = 1;
  375.     }
  376.     else {
  377.       criterion[0].comparison = comparator;
  378.       criterion[0].value = value;
  379.     }
  380.     *mode |= (1 << RGBA);
  381.     *mode |= (1 << RGBA_MODE);
  382.     return 1;
  383.       }
  384.       rgba = !strcmp(word, "rgba");
  385.       rgb = !strcmp(word, "rgb");
  386.       if (rgb || rgba) {
  387.     criterion[0].capability = RGBA;
  388.     criterion[0].comparison = EQ;
  389.     criterion[0].value = 1;
  390.  
  391.     criterion[1].capability = RED_SIZE;
  392.     criterion[2].capability = GREEN_SIZE;
  393.     criterion[3].capability = BLUE_SIZE;
  394.     criterion[4].capability = ALPHA_SIZE;
  395.     if (rgba) {
  396.       count = 5;
  397.     }
  398.     else {
  399.       count = 4;
  400.       criterion[4].comparison = MIN;
  401.       criterion[4].value = 0;
  402.     }
  403.     if (comparator == NONE) {
  404.       comparator = GTE;
  405.       value = 1;
  406.     }
  407.     for (i = 1; i < count; i++) {
  408.       criterion[i].comparison = comparator;
  409.       criterion[i].value = value;
  410.     }
  411.     *mode |= (1 << RGBA);
  412.     *mode |= (1 << RGBA_MODE);
  413.     return 5;
  414.       }
  415.       return -1;
  416.     case 's':
  417.       if (!strcmp(word, "stencil")) {
  418.     criterion[0].capability = STENCIL_SIZE;
  419.     if (comparator == NONE) {
  420.       criterion[0].comparison = MIN;
  421.       criterion[0].value = 1;
  422.     }
  423.     else {
  424.       criterion[0].comparison = comparator;
  425.       criterion[0].value = value;
  426.     }
  427.     *mode |= (1 << STENCIL_SIZE);
  428.     return 1;
  429.       }
  430.       if (!strcmp(word, "single")) {
  431.     criterion[0].capability = DOUBLEBUFFER;
  432.     if (comparator == NONE) {
  433.       criterion[0].comparison = EQ;
  434.       criterion[0].value = 0;
  435.       *allowDoubleAsSingle = True;
  436.       *mode |= (1 << DOUBLEBUFFER);
  437.       return 1;
  438.     }
  439.     else {
  440.       return -1;
  441.     }
  442.       }
  443.       if (!strcmp(word, "stereo")) {
  444.     criterion[0].capability = STEREO;
  445.     if (comparator == NONE) {
  446.       criterion[0].comparison = EQ;
  447.       criterion[0].value = 1;
  448.     }
  449.     else {
  450.       criterion[0].comparison = comparator;
  451.       criterion[0].value = value;
  452.     }
  453.     *mode |= (1 << STEREO);
  454.     return 1;
  455.       }
  456.       if (!strcmp(word, "samples")) {
  457.     criterion[0].capability = SAMPLES;
  458.     if (comparator == NONE) {
  459.       criterion[0].comparison = LTE;
  460.       criterion[0].value = 4;
  461.     }
  462.     else {
  463.       criterion[0].comparison = comparator;
  464.       criterion[0].value = value;
  465.     }
  466.     *mode |= (1 << SAMPLES);
  467.     return 1;
  468.       }
  469.       if (!strcmp(word, "slow")) {
  470.     criterion[0].capability = SLOW;
  471.     if (comparator == NONE) {
  472.       /* Just "slow" means permit fast visuals, but accept
  473.        * slow ones in preference. Presumably the slow ones
  474.        * must be higher quality or something else desirable. */
  475.       criterion[0].comparison = GTE;
  476.       criterion[0].value = 0;
  477.     }
  478.     else {
  479.       criterion[0].comparison = comparator;
  480.       criterion[0].value = value;
  481.     }
  482.     *mode |= (1 << SLOW);
  483.     return 1;
  484.       }
  485.       return -1;
  486.     case 'x':
  487.       /* Be a little over-eager to fill in the comparison and
  488.        * value so we won't have to replicate the code after each
  489.        * string match. */
  490.       if (comparator == NONE) {
  491.     criterion[0].comparison = EQ;
  492.     criterion[0].value = 1;
  493.       }
  494.       else {
  495.     criterion[0].comparison = comparator;
  496.     criterion[0].value = value;
  497.       }
  498.  
  499.       if (!strcmp(word, "xstaticgray")) {
  500.     criterion[0].capability = XSTATICGRAY;
  501.     *mode |= (1 << XSTATICGRAY);                /* Indicates _any_ visual
  502.                                  * class selected. */
  503.     return 1;
  504.       }
  505.       if (!strcmp(word, "xgrayscale")) {
  506.     criterion[0].capability = XGRAYSCALE;
  507.     *mode |= (1 << XSTATICGRAY);                /* Indicates _any_ visual
  508.                                  * class selected. */
  509.     return 1;
  510.       }
  511.       if (!strcmp(word, "xstaticcolor")) {
  512.     criterion[0].capability = XSTATICCOLOR;
  513.     *mode |= (1 << XSTATICGRAY);                /* Indicates _any_ visual
  514.                                  * class selected. */
  515.     return 1;
  516.       }
  517.       if (!strcmp(word, "xpseudocolor")) {
  518.     criterion[0].capability = XPSEUDOCOLOR;
  519.     *mode |= (1 << XSTATICGRAY);                /* Indicates _any_ visual
  520.                                  * class selected. */
  521.     return 1;
  522.       }
  523.       if (!strcmp(word, "xtruecolor")) {
  524.     criterion[0].capability = XTRUECOLOR;
  525.     *mode |= (1 << XSTATICGRAY);                /* Indicates _any_ visual
  526.                                  * class selected. */
  527.     return 1;
  528.       }
  529.       if (!strcmp(word, "xdirectcolor")) {
  530.     criterion[0].capability = XDIRECTCOLOR;
  531.     *mode |= (1 << XSTATICGRAY);                /* Indicates _any_ visual
  532.                                  * class selected. */
  533.     return 1;
  534.       }
  535.       return -1;
  536.     default:
  537.       return -1;
  538.   }
  539. }
  540.  
  541. Criterion *parseModeString(char *mode, int *ncriteria, BOOL *allowDoubleAsSingle,
  542.                Criterion *requiredCriteria, int nRequired, int requiredMask)
  543. {
  544.   Criterion *criteria = NULL;
  545.   int n, mask, parsed, i;
  546.   char *copy, *word;
  547.  
  548.   *allowDoubleAsSingle = FALSE;
  549.   copy = strdup(mode);
  550.   /* Attempt to estimate how many criteria entries should be
  551.    * needed.
  552.    */
  553.   n = 0;
  554.   word = strtok(copy, " \t");
  555.   while (word) {
  556.     n++;
  557.     word = strtok(NULL, " \t");
  558.   }
  559.   /* Overestimate by 4 times ("rgba" might add four criteria
  560.    * entries) plus add in possible defaults plus space for
  561.    * required criteria.
  562.    */
  563.   if ((criteria = (Criterion *)malloc((4 * n + 30 + nRequired) * sizeof(Criterion)))) {
  564.   /* Re-copy the copy of the mode string. */
  565.   strcpy(copy, mode);
  566.  
  567.   /* First add the required criteria (these match at the
  568.    * highest priority). Typically these will be used to force a
  569.    * specific level (layer), transparency, and/or visual type.
  570.    */
  571.   mask = requiredMask;
  572.   for (i = 0; i < nRequired; i++)
  573.     criteria[i] = requiredCriteria[i];
  574.   n = nRequired;
  575.  
  576.   word = strtok(copy, " \t");
  577.   while (word) {
  578.     parsed = parseCriteria(word, &criteria[n], &mask, allowDoubleAsSingle);
  579.     if (parsed >= 0)
  580.       n += parsed;
  581.     else
  582.       Printf("Unrecognized display string word: %s (ignoring)\n", word);
  583.     word = strtok(NULL, " \t");
  584.   }
  585.  
  586.   if (!(mask & (1 << ACCUM_RED_SIZE))) {
  587.     criteria[n].capability = ACCUM_RED_SIZE;
  588.     criteria[n].comparison = MIN;
  589.     criteria[n].value = 0;
  590.     criteria[n + 1].capability = ACCUM_GREEN_SIZE;
  591.     criteria[n + 1].comparison = MIN;
  592.     criteria[n + 1].value = 0;
  593.     criteria[n + 2].capability = ACCUM_BLUE_SIZE;
  594.     criteria[n + 2].comparison = MIN;
  595.     criteria[n + 2].value = 0;
  596.     criteria[n + 3].capability = ACCUM_ALPHA_SIZE;
  597.     criteria[n + 3].comparison = MIN;
  598.     criteria[n + 3].value = 0;
  599.     n += 4;
  600.   }
  601.   if (!(mask & (1 << AUX_BUFFERS))) {
  602.     criteria[n].capability = AUX_BUFFERS;
  603.     criteria[n].comparison = MIN;
  604.     criteria[n].value = 0;
  605.     n++;
  606.   }
  607.   if (!(mask & (1 << RGBA))) {
  608.     criteria[n].capability = RGBA;
  609.     criteria[n].comparison = EQ;
  610.     criteria[n].value = 1;
  611.     criteria[n + 1].capability = RED_SIZE;
  612.     criteria[n + 1].comparison = GTE;
  613.     criteria[n + 1].value = 1;
  614.     criteria[n + 2].capability = GREEN_SIZE;
  615.     criteria[n + 2].comparison = GTE;
  616.     criteria[n + 2].value = 1;
  617.     criteria[n + 3].capability = BLUE_SIZE;
  618.     criteria[n + 3].comparison = GTE;
  619.     criteria[n + 3].value = 1;
  620.     criteria[n + 4].capability = ALPHA_SIZE;
  621.     criteria[n + 4].comparison = MIN;
  622.     criteria[n + 4].value = 0;
  623.     n += 5;
  624.     mask |= (1 << RGBA_MODE);
  625.   }
  626.  
  627.   if (!(mask & (1 << XSTATICGRAY))) {
  628.     if ((mask & (1 << RGBA_MODE))) {
  629.       /* Normally, request an RGBA mode visual be TrueColor,
  630.        * except in the case of Mesa where we trust Mesa (and
  631.        * other code in GLUT) to handle any type of RGBA visual
  632.        * reasonably.
  633.        */
  634.       if (mask & (1 << LUMINANCE_MODE))
  635.     /* If RGBA luminance was requested, actually go for
  636.      * a StaticGray visual.
  637.          */
  638.         criteria[n].capability = XSTATICGRAY;
  639.       else
  640.         criteria[n].capability = XTRUECOLOR;
  641.       criteria[n].value = 1;
  642.       criteria[n].comparison = EQ;
  643.  
  644.       n++;
  645.     }
  646.     if (mask & (1 << CI_MODE)) {
  647.       criteria[n].capability = XPSEUDOCOLOR;
  648.       criteria[n].value = 1;
  649.       criteria[n].comparison = EQ;
  650.       n++;
  651.     }
  652.   }
  653.  
  654.   if (!(mask & (1 << STEREO))) {
  655.     criteria[n].capability = STEREO;
  656.     criteria[n].comparison = EQ;
  657.     criteria[n].value = 0;
  658.     n++;
  659.   }
  660.   if (!(mask & (1 << DOUBLEBUFFER))) {
  661.     criteria[n].capability = DOUBLEBUFFER;
  662.     criteria[n].comparison = EQ;
  663.     criteria[n].value = 0;
  664.     *allowDoubleAsSingle = True;
  665.     n++;
  666.   }
  667.   if (!(mask & (1 << DEPTH_SIZE))) {
  668.     criteria[n].capability = DEPTH_SIZE;
  669.     criteria[n].comparison = MIN;
  670.     criteria[n].value = 0;
  671.     n++;
  672.   }
  673.   if (!(mask & (1 << STENCIL_SIZE))) {
  674.     criteria[n].capability = STENCIL_SIZE;
  675.     criteria[n].comparison = MIN;
  676.     criteria[n].value = 0;
  677.     n++;
  678.   }
  679.   if (!(mask & (1 << LEVEL))) {
  680.     criteria[n].capability = LEVEL;
  681.     criteria[n].comparison = EQ;
  682.     criteria[n].value = 0;
  683.     n++;
  684.   }
  685.  
  686.   if (n) {
  687.     /* Since over-estimated the size needed; squeeze it down to
  688.      * reality.
  689.      */
  690.     if (!(criteria = (Criterion *) realloc(criteria, n * sizeof(Criterion))))
  691.       return NULL;
  692.   }
  693.   else {
  694.     /* For portability, avoid "realloc(ptr,0)" call. */
  695.     free(criteria);
  696.     criteria = NULL;
  697.   }
  698.  
  699.   free(copy);
  700.   *ncriteria = n;
  701.   }
  702.  
  703.   return criteria;
  704. }
  705.  
  706. /* converts criterion to mode */
  707. int critToMode(int mode)
  708. {
  709.   return 0;
  710. }
  711.  
  712. void glutInitDisplayString(const char *string)
  713. {
  714.   char *this, *next, *old;
  715.   int mode;
  716.  
  717.   old = this = strdup(string);
  718.   while ((next = strstr(this, ' '))) {
  719.     *next++ = 0;
  720.     while (*next == ' ')
  721.       next++;
  722.  
  723.     if (*this) {
  724.       if (parseString(this, &mode) > 0)
  725.     glutInitDisplayMode(critToMode(mode));
  726.     }
  727.     this = next;
  728.   }
  729.  
  730.   if (*this) {
  731.     if (parseString(this, &mode) > 0)
  732.       glutInitDisplayMode(critToMode(mode));
  733.   }
  734.  
  735.   free(old);
  736. }
  737.